/*! \file Mary2Client.h
    \brief Communicates with the Mary server.
	Head X | Flinders University | Trent Lewis & Martin Luerssen | 2009+
*/

#pragma once

#include <winsock2.h>
#pragma warning(disable : 4201)
#include <Mmsystem.h>
#include <string>
#include <sstream>
//#include <sstream.h>
//#include "DirectSound.h"

using namespace std;

class MaryVoice
{
public:
	MaryVoice(const string& voiceString);
	~MaryVoice();

	string GetName();
	string GetLocale();
	bool IsValid();

private:

	string source;
	string name;
	string locale;
	bool valid;

};
	

class MaryClient
{
public:
	MaryClient(const string& _server_host, int _server_port);
	~MaryClient(void);

	int process(const string& inputText,
			const string& maryInFormat,
			const string& maryOutFormat,
			const string& locale,
			const string& audioType,
			const string& voiceName,
			const string& effects,
			string& result);

	int process(const string& inputText, string& result);
	int play(string& result, HWAVEOUT &hWaveOut, WAVEHDR &waveHdr, double* factor);

	int setTypes(const string& _inputType, const string& _outputType, const string& _audioType, const string& _voiceName, const string& _effects);
	int setInputType(const string& _inputType);
	int setOutputType(const string& _outputType);
	int setAudioType(const string& _audioType);
	int setVoiceName(const string& _voiceName);
	int setEffects(const string& _effects);

	int getVoices(vector<string>& voices);

	string getOutputType();

	string getErrorString(int errorCode);

	// error codes
	static const int ERROR_NONE = 0;
	static const int ERROR_SERVER_CONNECT = -1;
	static const int ERROR_INFO_SOCKET_CREATE = -2;
	static const int ERROR_INFO_SOCKET_BIND = -3;
	static const int ERROR_INFO_SOCKET_CONNECT = -4;
	static const int ERROR_DATA_SOCKET_CREATE = -5;
	static const int ERROR_DATA_SOCKET_BIND = -6;
	static const int ERROR_DATA_SOCKET_CONNECT = -7;

	static const int ERROR_INFO_SENDING_REQUEST = -8;
	static const int ERROR_INFO_RECEIVING_ID = -9;
	static const int ERROR_DATA_SENDING_ID = -10;
	static const int ERROR_DATA_SENDING_TEXT = -11;
	static const int ERROR_DATA_RECEIVING_DATA = -12;

	
	static const int ERROR_PLAY_READ_WAVE_FAIL = -13;
	static const int ERROR_PLAY_OPEN_DEVICE_FAIL = -14;
	static const int ERROR_PLAY_WRITE_DEVICE_FAIL = -15;

	static const int ERROR_INFO_MALFORMED_REQUEST = -16;



private:
	// server
	string server_host;
	int server_port;
	
	// sockects
	int maryInfoSocket;
	int maryDataSocket;

	//  connection stuff
	struct sockaddr_in maryServer;
	struct sockaddr_in maryClient;
	struct hostent* hostInfo;

	bool connected;
	bool infoSent;

	// types
	string inputType;
	string outputType;
	string audioType;
	string voiceName;
	string locale;
	string effects;

	vector<MaryVoice*> voiceList;

	int connectInfoSocket();
	int connectDataSocket();
	int connectToServer();
	int sendInfoRequest(const string& maryInFormat,const string& maryOutFormat,const string& locale, const string& audioType,const string& voiceName, const string& effects, char* id);
	int sendDataRequest(const string& inputText, char* id);

	int readandfill(int maryDataSocket, string& result);

	BOOL GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, void * & pbWaveData, DWORD & cbWaveSize);
};
